package com.mango.wall.activities;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.content.FileProvider;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckedTextView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.mango.config.BaseWall;
import com.mango.downloader.Error;
import com.mango.downloader.OnCancelListener;
import com.mango.downloader.OnDownloadListener;
import com.mango.downloader.OnPauseListener;
import com.mango.downloader.OnProgressListener;
import com.mango.downloader.OnStartOrResumeListener;
import com.mango.downloader.PRDownloader;
import com.mango.downloader.Progress;
import com.mango.downloader.Status;
import com.mango.imageloader.core.DisplayImageOptions;
import com.mango.imageloader.core.display.RoundedBitmapDisplayer;
import com.mango.request.ReqMgAdList;
import com.mango.request.ReqMgUserLogin;
import com.mango.request.ReqMgWallReport;
import com.mango.request.beans.AdvertBean;
import com.mango.request.beans.UserLoginBean;
import com.mango.volley.Response;
import com.mango.volley.VolleyError;
import com.mango.volley.toolbox.RequestFuture;
import com.mango.volley.toolbox.StringRequest;
import com.mango.wall.R;
import com.mango.wall.dialogs.InstallCompleteDialog;
import com.mango.wall.dialogs.TaskCompleteDialog;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;

public class WallActivity extends Activity {
    private static final int REQUEST_TRIAL = 1000;
    private static final int REQUEST_START = 1001;

    private int posID;
    private String userID;
    private String savePath;

    private ListView list;
    private WallAdapter adapter;

    private TextView pointsView;

    private long currentTime;
    private String currentUUID;
    private AdvertBean currentTask;
    private CheckedTextView currentView;

    private UserLoginBean userInfo = null;
    private final List<AdvertBean> trialList = new ArrayList<>();
    private final List<AdvertBean> downloadList = new ArrayList<>();
    private final Map<Integer, ProgressController> progressList = new HashMap<>();

    private final DisplayImageOptions options1
            = new DisplayImageOptions.Builder()
            .showImageOnFail(R.drawable.mg_wall_ic_default)
            .showImageOnLoading(R.drawable.mg_wall_ic_default)
            .showImageForEmptyUri(R.drawable.mg_wall_ic_default)
            .displayer(new RoundedBitmapDisplayer((int) TypedValue.applyDimension(
                    TypedValue.COMPLEX_UNIT_DIP, 5, BaseWall.getInstance()
                            .getApplication().getResources().getDisplayMetrics()))).build();

    private final DisplayImageOptions options2
            = new DisplayImageOptions.Builder()
            .showImageOnFail(R.drawable.mg_wall_ic_default)
            .showImageOnLoading(R.drawable.mg_wall_ic_default)
            .showImageForEmptyUri(R.drawable.mg_wall_ic_default)
            .displayer(new RoundedBitmapDisplayer((int) TypedValue.applyDimension(
                    TypedValue.COMPLEX_UNIT_DIP, 15, BaseWall.getInstance()
                            .getApplication().getResources().getDisplayMetrics()))).build();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mg_wall_activity);

        userID = getIntent().getStringExtra("userID");
        posID = getIntent().getIntExtra("posID", 0);
        savePath = new File(getCacheDir(), "ManGo").getAbsolutePath();

        list = findViewById(R.id.list);
        list.setAdapter(adapter = new WallAdapter());

        appStatusReceiver = new AppStatusReceiver();
        registerInstallation();

        loadThread.start();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (currentTask == null) return;

        switch (requestCode) {
            case REQUEST_TRIAL:
                if ((System.currentTimeMillis() - currentTime) / 1000
                        >= BaseWall.getInstance().getConfig().comm.deeplinkSecond) {
                    showTaskComplete();
                    currentView.setChecked(true);
                    currentView.setText("已领取");
                    ReportWall(currentTask, currentUUID, 0, 1);
                }
                break;
            case REQUEST_START:
                if ((System.currentTimeMillis() - currentTime) / 1000
                        >= BaseWall.getInstance().getConfig().comm.downSecond) {
                    showTaskComplete();
                    adapter.notifyDataSetChanged();
                    ReportWall(currentTask, currentUUID, 1, 1);
                }
                break;
        }
    }

    @Override
    @SuppressWarnings("ResultOfMethodCallIgnored")
    protected void onDestroy() {
        super.onDestroy();

        PRDownloader.cancelAll();
        unregisterReceiver(appStatusReceiver);
        File[] files = new File(savePath).listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isFile() && file.getName()
                        .contains(".apk")) file.delete();
            }
        }
    }

    private final Thread loadThread = new Thread() {
        @Override
        public void run() {
            while (BaseWall.getInstance().getConfig() == null) {
                sleep();
            }

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    TextView title = findViewById(R.id.title);
                    title.setText(String.format(Locale.getDefault(), "试玩领%s",
                            BaseWall.getInstance().getConfig().comm.integralName));
                }
            });

            RequestFuture<UserLoginBean> future1 = RequestFuture.newFuture();
            RequestFuture<Map<Integer, List<AdvertBean>>> future2 = RequestFuture.newFuture();

            do {
                BaseWall.getInstance().getQueue().add(new ReqMgUserLogin(BaseWall.getInstance()
                        .getAppID(), BaseWall.getInstance().getAppKey(), userID, future1, future1));

                try {
                    userInfo = future1.get();
                } catch (Exception exception) {
                    sleep();
                    future1 = RequestFuture.newFuture();
                }
            } while (!WallActivity.this.isFinishing() && !future1.isDone());
            if (WallActivity.this.isFinishing()) return;

            do {
                BaseWall.getInstance().getQueue().add(new ReqMgAdList(BaseWall.getInstance().getAppID(),
                        BaseWall.getInstance().getAppKey(), 1, 2, posID, userID, future2, future2));

                try {
                    Map<Integer, List<AdvertBean>> adverts = future2.get();
                    if (!adverts.containsKey(posID)) break;

                    List<AdvertBean> list = adverts.get(posID);
                    if (list == null) break;

                    for (AdvertBean item : list) {
                        if (!TextUtils.isEmpty(item
                                .adConversionInfo.deeplinkUrl))
                            trialList.add(item);
                        else
                            downloadList.add(item);
                    }
                } catch (Exception exception) {
                    sleep();
                    future2 = RequestFuture.newFuture();
                }
            } while (!WallActivity.this.isFinishing() && !future2.isDone());

            if (WallActivity.this.isFinishing()) return;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    initTrials();
                    adapter.notifyDataSetChanged();

                    for (AdvertBean item : trialList) {
                        Report(item, AdvertBean.ActionType.SHOW);
                    }
                    for (AdvertBean item : downloadList) {
                        Report(item, AdvertBean.ActionType.SHOW);
                    }
                }
            });
        }

        private void sleep() {
            try {
                Thread.sleep(1000);
            } catch (Exception exception2) {
                // Do nothing.
            }
        }
    };

    private void setTrialItem(AdvertBean advert, ImageView img, TextView txt,
                              CheckedTextView border, CheckedTextView status) {
        if (advert == null) {
            img.setImageResource(R.drawable.mg_wall_ic_default);
            txt.setText("待上新");
            border.setChecked(false);
            status.setChecked(true);
            status.setText("上新中");
            status.setTag(null);
        } else {
            BaseWall.getInstance().getImageLoader()
                    .displayImage(advert.adBaseInfo.appIconUrl, img, options2);
            txt.setText(advert.adBaseInfo.appName);
            border.setChecked(true);
            status.setChecked(false);
            status.setText(String.format(Locale.getDefault(), "+%d%s",
                    advert.adBaseInfo.integral, BaseWall.getInstance().getConfig().comm.integralName));

            status.setTag(advert);
            status.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (v.getTag() instanceof AdvertBean) {
                        AdvertBean advert = (AdvertBean) v.getTag();
                        currentTime = System.currentTimeMillis();
                        currentUUID = UUID.randomUUID().toString().replace("-", "");
                        currentView = (CheckedTextView) v;
                        currentTask = advert;

                        startActivityForResult(new Intent(Intent.ACTION_VIEW, Uri.parse(
                                advert.adConversionInfo.deeplinkUrl)), REQUEST_TRIAL);
                        ReportWall(currentTask, currentUUID, 0, 0);
                        Report(advert, AdvertBean.ActionType.CLICK_DEEPLINK);
                    }
                }
            });
        }
    }

    private void initTrials() {
        View header = getLayoutInflater().inflate(R.layout
                .mg_wall_view_trials, list, false);
        list.addHeaderView(header);

        DisplayMetrics metrics = getResources().getDisplayMetrics();
        View banner_content = header.findViewById(R.id.mg_wall_banner);
        banner_content.getLayoutParams().height = (int) (metrics.widthPixels / 1080F * 380F);

        TextView points_rest = header.findViewById(R.id.mg_wall_points_rest);
        points_rest.setText(String.format(Locale.getDefault(),
                "可用试玩%s", BaseWall.getInstance().getConfig().comm.integralName));

        pointsView = header.findViewById(R.id.mg_wall_points);
        pointsView.setText(String.format(Locale.getDefault(), "%.2f", userInfo.user.integral));

        TextView timeTrial = header.findViewById(R.id.mg_wall_trial_time);
        timeTrial.setText(String.format(Locale.getDefault(),
                "%d秒", BaseWall.getInstance().getConfig().comm.deeplinkSecond));

        TextView step03 = header.findViewById(R.id.mg_wall_step03);
        step03.setText(String.format(Locale.getDefault(),
                "领取%s", BaseWall.getInstance().getConfig().comm.integralName));

        TextView name1 = header.findViewById(R.id.mg_wall_name1);
        name1.setText(String.format(Locale.getDefault(), "领%s",
                BaseWall.getInstance().getConfig().comm.integralName));

        TextView timeDownload = header.findViewById(R.id.mg_wall_download_time);
        timeDownload.setText(String.format(Locale.getDefault(),
                "%d秒", BaseWall.getInstance().getConfig().comm.downSecond));

        TextView name2 = header.findViewById(R.id.mg_wall_name2);
        name2.setText(String.format(Locale.getDefault(), "领%s",
                BaseWall.getInstance().getConfig().comm.integralName));

        ImageView trialImg1 = findViewById(R.id.mg_wall_trial_img1);
        TextView trialTxt1 = findViewById(R.id.mg_wall_trial_txt1);
        CheckedTextView trialBorder1 = findViewById(R.id.mg_wall_trial_border1);
        CheckedTextView trialStatus1 = findViewById(R.id.mg_wall_trial_status1);

        ImageView trialImg2 = findViewById(R.id.mg_wall_trial_img2);
        TextView trialTxt2 = findViewById(R.id.mg_wall_trial_txt2);
        CheckedTextView trialBorder2 = findViewById(R.id.mg_wall_trial_border2);
        CheckedTextView trialStatus2 = findViewById(R.id.mg_wall_trial_status2);

        ImageView trialImg3 = findViewById(R.id.mg_wall_trial_img3);
        TextView trialTxt3 = findViewById(R.id.mg_wall_trial_txt3);
        CheckedTextView trialBorder3 = findViewById(R.id.mg_wall_trial_border3);
        CheckedTextView trialStatus3 = findViewById(R.id.mg_wall_trial_status3);

        setTrialItem(trialList.size() < 1 ? null : trialList.get(0), trialImg1, trialTxt1, trialBorder1, trialStatus1);
        setTrialItem(trialList.size() < 2 ? null : trialList.get(1), trialImg2, trialTxt2, trialBorder2, trialStatus2);
        setTrialItem(trialList.size() < 3 ? null : trialList.get(2), trialImg3, trialTxt3, trialBorder3, trialStatus3);

        list.addFooterView(getLayoutInflater().inflate(
                R.layout.mg_wall_view_bottom, list, false));
    }

    private class ViewHolder implements View.OnClickListener {
        private int position;
        private final ImageView img;
        private final TextView txt, intro, coin, download;

        private final RelativeLayout progress;
        private final ProgressBar progress_bar;
        private final TextView progress_txt;

        private ViewHolder(View convertView) {
            position = -1;

            img = convertView.findViewById(R.id.mg_wall_img);
            txt = convertView.findViewById(R.id.mg_wall_txt);
            intro = convertView.findViewById(R.id.mg_wall_intro);
            coin = convertView.findViewById(R.id.mg_wall_coin);

            download = convertView.findViewById(R.id.mg_wall_download);
            download.setOnClickListener(this);

            progress = convertView.findViewById(R.id.mg_wall_progress);
            progress_bar = convertView.findViewById(R.id.mg_wall_progress_bar);
            progress_txt = convertView.findViewById(R.id.mg_wall_progress_txt);
        }

        @Override
        public void onClick(View v) {
            AdvertBean advert = adapter.getItem(position);
            if (advert.hasDone) return;

            ProgressController controller = progressList.get(position);

            if (controller == null || (PRDownloader.getStatus(controller.downloadID) != Status.UNKNOWN
                    && PRDownloader.getStatus(controller.downloadID) != Status.COMPLETED)) {
                progressList.put(position, controller = new ProgressController());
                controller.bindViewHolder(this);

                controller.position = position;
                controller.downloadID = PRDownloader.download(advert.adConversionInfo.appDownloadUrl, savePath,
                                controller.saveName = advert.adBaseInfo.appPackageName + ".apk").build()
                        .setOnPauseListener(controller).setOnCancelListener(controller)
                        .setOnStartOrResumeListener(controller)
                        .setOnProgressListener(controller)
                        .start(controller);
            } else {
                Intent intent = getPackageManager()
                        .getLaunchIntentForPackage(advert.adBaseInfo.appPackageName);
                if (intent != null) {
                    currentTime = System.currentTimeMillis();
                    currentTask = downloadList.get(position);
                    currentUUID = UUID.randomUUID().toString().replace("-", "");
                    moveTaskToBack(true);
                    startActivityForResult(intent, REQUEST_START);
                    ReportWall(currentTask, currentUUID, 1, 0);
                    Report(currentTask, AdvertBean.ActionType.ACTIVATION);
                } else {
                    File file = new File(savePath + File.separator + controller.saveName);
                    intent = new Intent(Intent.ACTION_VIEW);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                        intent.setDataAndType(FileProvider.getUriForFile(WallActivity.this,
                                        getPackageName() + ".fileprovider", file),
                                "application/vnd.android.package-archive");
                    } else
                        intent.setDataAndType(Uri.fromFile(file),
                                "application/vnd.android.package-archive");

                    currentTime = System.currentTimeMillis();
                    currentTask = downloadList.get(position);
                    startActivity(intent);
                    Report(currentTask, AdvertBean.ActionType.INSTALL_START);
                }
            }
        }
    }

    private class ProgressController implements OnStartOrResumeListener,
            OnPauseListener, OnCancelListener, OnProgressListener, OnDownloadListener {
        private int position;
        private String saveName;
        private ViewHolder viewHolder;
        private int downloadID, progress;

        public synchronized void bindViewHolder(ViewHolder holder) {
            viewHolder = holder;
        }

        @Override
        public synchronized void onStartOrResume() {
            Report(adapter.getItem(position),
                    AdvertBean.ActionType.DOWN_START);

            if (viewHolder == null) return;
            viewHolder.download.setVisibility(View.INVISIBLE);
            viewHolder.progress.setVisibility(View.VISIBLE);

            viewHolder.progress_bar.setProgress(progress);
            viewHolder.progress_txt.setText(String.format(
                    Locale.getDefault(), "%d%%", progress));
        }

        @Override
        public synchronized void onError(Error error) {
            onCancel();
        }

        @Override
        public synchronized void onCancel() {
            Report(adapter.getItem(position),
                    AdvertBean.ActionType.DOWN_STOP);

            progressList.remove(position);
            if (viewHolder == null) return;

            viewHolder.download.setText("立即下载");
            viewHolder.download.setVisibility(View.VISIBLE);
            viewHolder.progress.setVisibility(View.INVISIBLE);
        }

        @Override
        public synchronized void onPause() {
            PRDownloader.cancel(downloadID);
        }

        @Override
        public synchronized void onProgress(Progress progress) {
            this.progress = (int) (progress.currentBytes * 100 / progress.totalBytes);

            if (viewHolder == null) return;
            viewHolder.progress_bar.setProgress(this.progress);
            viewHolder.progress_txt.setText(String.format(
                    Locale.getDefault(), "%d%%", this.progress));
        }

        @Override
        public synchronized void onDownloadComplete() {
            Report(adapter.getItem(position),
                    AdvertBean.ActionType.DOWN_END);

            if (viewHolder == null) return;

            viewHolder.download.setText("立即体验");
            viewHolder.download.setVisibility(View.VISIBLE);
            viewHolder.progress.setVisibility(View.INVISIBLE);
        }
    }

    private class WallAdapter extends BaseAdapter {
        @Override
        public int getCount() {
            return downloadList.size();
        }

        @Override
        public AdvertBean getItem(int position) {
            return downloadList.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null) {
                convertView = getLayoutInflater().inflate(
                        R.layout.mg_wall_view_download, list, false);
                convertView.setTag(holder = new ViewHolder(convertView));
            } else {
                holder = (ViewHolder) convertView.getTag();
                ProgressController controller = progressList.get(holder.position);
                if (controller != null) controller.bindViewHolder(null);
            }

            holder.position = position;
            AdvertBean advert = getItem(position);
            BaseWall.getInstance().getImageLoader().displayImage(advert.adBaseInfo.appIconUrl, holder.img, options1);
            holder.txt.setText(advert.adBaseInfo.appName);
            holder.intro.setText(advert.adBaseInfo.adDescription);
            holder.coin.setText(String.format(Locale.getDefault(), "+%d", advert.adBaseInfo.integral));

            if (advert.hasDone) {
                holder.download.setText("\u0020\u0020已领取\u0020\u0020");
                holder.download.setVisibility(View.VISIBLE);
                holder.progress.setVisibility(View.INVISIBLE);
                return convertView;
            }

            ProgressController controller = progressList.get(holder.position);
            if (controller == null) {
                holder.download.setText("立即下载");
                holder.download.setVisibility(View.VISIBLE);
                holder.progress.setVisibility(View.INVISIBLE);
            } else {
                controller.bindViewHolder(holder);
                Status status = PRDownloader.getStatus(controller.downloadID);
                if (status == Status.QUEUED || status == Status.RUNNING) {
                    holder.download.setVisibility(View.INVISIBLE);
                    holder.progress.setVisibility(View.VISIBLE);
                    holder.progress_bar.setProgress(controller.progress);
                    holder.progress_txt.setText(String.format(Locale.getDefault(), "%d%%", controller.progress));
                } else {
                    holder.download.setText(status == Status.UNKNOWN || status == Status.COMPLETED ? "立即体验" : "立即下载");
                    holder.download.setVisibility(View.VISIBLE);
                    holder.progress.setVisibility(View.INVISIBLE);
                }
            }
            return convertView;
        }
    }

    private final Handler handler = new Handler();

    private class RetryListener implements Response.ErrorListener, Runnable {
        private String url;

        private RetryListener(String url) {
            this.url = url;
        }

        @Override
        public void run() {
            if (WallActivity.this.isFinishing()) return;
            BaseWall.getInstance().getQueue().add(
                    new StringRequest(url, null, this));
        }

        @Override
        public void onErrorResponse(VolleyError error) {
            if (WallActivity.this.isFinishing()) return;
            handler.postDelayed(this, 3000);
        }
    }

    private void Report(AdvertBean advert, AdvertBean.ActionType type) {
        String[] urls = advert.adBaseInfo.convUrl.get(type);
        if (urls == null) return;
        for (String url : urls) {
            BaseWall.getInstance().getQueue().add(
                    new StringRequest(url, null, new RetryListener(url)));
        }
    }

    private void ReportWall(AdvertBean advert, String transId, int adType, int type) {
        RetryListener listener = new RetryListener(null);
        ReqMgWallReport request = new ReqMgWallReport(BaseWall.getInstance().getAppID(),
                BaseWall.getInstance().getAppKey(), advert.adBaseInfo.adid, adType,
                userID, transId, type, null, listener);

        listener.url = request.getUrl();
        BaseWall.getInstance().getQueue().add(request);
    }

    private AppStatusReceiver appStatusReceiver;

    public class AppStatusReceiver extends BroadcastReceiver implements Runnable {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (currentTask == null) return;
            switch (intent.getAction()) {
                case Intent.ACTION_PACKAGE_ADDED:
                case Intent.ACTION_PACKAGE_REPLACED:
                    if (getPackageManager().getLaunchIntentForPackage(currentTask
                            .adBaseInfo.appPackageName) != null) {
                        Report(currentTask, AdvertBean.ActionType.INSTALL_END);
                        handler.postDelayed(this, 100);
                    }
                    break;
            }
        }

        @Override
        public void run() {
            new InstallCompleteDialog(WallActivity.this, currentTask)
                    .setOnConfirmListener(new InstallCompleteDialog.OnConfirmListener() {
                        @Override
                        public void onConfirm() {
                            currentTime = System.currentTimeMillis();
                            currentUUID = UUID.randomUUID().toString()
                                    .replace("-", "");

                            moveTaskToBack(true);
                            startActivityForResult(getPackageManager().getLaunchIntentForPackage(
                                    currentTask.adBaseInfo.appPackageName), REQUEST_START);
                            ReportWall(currentTask, currentUUID, 1, 0);
                            Report(currentTask, AdvertBean.ActionType.ACTIVATION);
                        }
                    }).show();
            startActivity(new Intent(WallActivity.this, WallActivity.class)
                    .addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT));
        }
    }

    private void registerInstallation() {
        IntentFilter filter = new IntentFilter();
        filter.addDataScheme("package");
        filter.addAction(Intent.ACTION_PACKAGE_ADDED);
        filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
        registerReceiver(appStatusReceiver, filter);
    }

    private void showTaskComplete() {
        currentTask.hasDone = true;
        userInfo.user.integral += currentTask.adBaseInfo.integral;
        pointsView.setText(String.format(Locale.getDefault(), "%.2f", userInfo.user.integral));

        new TaskCompleteDialog(this, currentTask).show();
    }
}
